using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Device_Link_LTSMC
{
	public class Device_Net_LSTMC
	{
		/// <summary>
		/// 连接号
		/// </summary>
		public ushort ConnectNo { get; protected set; } = 0;
		/// <summary>
		/// 目前设备的ip
		/// </summary>
		public string TargetIP { get; set; } = "192.168.5.11";
		/// <summary>
		/// 轴列表
		/// </summary>
		protected Dictionary<Axis, LTSMC_Axis> LtsmcAxiss { get; set; } = new Dictionary<Axis, LTSMC_Axis>();
		/// <summary>
		/// 是否连接状态
		/// </summary>
		private bool _isLink = false;
		public bool IsLink
		{
			get
			{
				return _isLink;
			}
			protected set
			{
				_isLink = value;
				ModifyAxissIsLink(value);
			}
		}
		/// <summary>
		/// 当前使用的坐标系
		/// </summary>
		private ushort _currentCrd = 0;
		/// <summary>
		/// 使用的坐标系
		/// </summary>
		public ushort CurrentCrd
		{
			get
			{
				return _currentCrd;
			}
			set
			{
				if (_currentCrd != ushort.MaxValue)
				{
					LTSMC.smc_stop(_currentCrd, _currentCrd, 0);
				}
				_currentCrd = value;
			}
		}
		/// <summary>
		/// 轴索引
		/// </summary>
		/// <param name="axis"></param>
		/// <returns></returns>
		public LTSMC_Axis this[Axis axis]
		{
			get
			{
				if (LtsmcAxiss.Keys.Contains(axis))
				{
					return LtsmcAxiss[axis];
				}
				return null;
			}
		}
		/// <summary>
		/// 所有的轴是否处于空闲状态
		/// </summary>
		public bool IsAllReady
		{
			get
			{
				foreach (KeyValuePair<Axis, LTSMC_Axis> item in LtsmcAxiss)
				{
					if (item.Value.GetAxisCurrentState())
					{
						return false;
					}
				}
				return true;
			}
		}
		/// <summary>
		/// 是否所有的轴都没有警告
		/// </summary>
		public bool IsAllNoWaring
		{
			get
			{
				foreach (KeyValuePair<Axis, LTSMC_Axis> item in LtsmcAxiss)
				{
					if (item.Value.IsWaring)
					{
						return false;
					}
				}
				return true;
			}
		}
		/// <summary>
		/// 轴异常事件
		/// </summary>
		public event AxisErroCallBack ErroCallBack = null;
		/// <summary>
		/// 检查是否已经连接
		/// </summary>
		/// <exception cref="LSTMCException"></exception>
		protected void CheckLinked()
		{
			if (!IsLink)
			{
				throw new LSTMCException("请先连接设备!");
			}
		}
		/// <summary>
		/// 默认构造函数 默认构造XY2个轴
		/// </summary>
		public Device_Net_LSTMC()
		{
			LtsmcAxiss.Add(Axis.X, LTSMC_Axis.Instance(Axis.X, ConnectNo));
			LtsmcAxiss.Add(Axis.Y, LTSMC_Axis.Instance(Axis.Y, ConnectNo));
			Init();
		}

		public Device_Net_LSTMC(List<Axis> axisList)
		{
			LtsmcAxiss.Clear();
			foreach (Axis axis in axisList)
			{
				if (!LtsmcAxiss.Keys.Contains(axis))
				{
					LtsmcAxiss.Add(axis, LTSMC_Axis.Instance(axis, ConnectNo));
				}
			}
			Init();
		}
		/// <summary>
		/// 初始化事件
		/// </summary>
		protected void Init()
		{
			foreach (KeyValuePair<Axis, LTSMC_Axis> item in LtsmcAxiss)
			{
				item.Value.ErroCallBack = this.ErroCallBack;
			}
		}
		/// <summary>
		/// 连接设备
		/// </summary>
		public void LinkDevice()
		{
			short num = LTSMC.smc_board_init(ConnectNo, 2, TargetIP, 115200u);
			if (num != 0)
			{
				CallBack("LinkDevice", num);
			}
			IsLink = true;
		}
		/// <summary>
		/// 直线插补
		/// </summary>
		/// <param name="data"></param>
		/// <param name="crd"></param>
		/// <exception cref="LSTMCException"></exception>
		public void SetLineInter(LineInterData data)
		{
			CheckLinked();
			ushort num = (ushort)data.AxisDatas.Count;
			ushort[] array = new ushort[num];
			double[] array2 = new double[num];
			int num2 = 0;
			foreach (var item in data.AxisDatas)
			{
				if (this[item.Key] == null)
				{
					throw new LSTMCException("插补没有添加的轴向!");
				}
				array[num2] = (ushort)item.Key;
				array2[num2++] = item.Value;
			}
			LTSMC.smc_set_vector_profile_unit(ConnectNo, CurrentCrd, 0.0, data.MaxSpeed, data.AccTime, data.DecTime, 0.0);
			LTSMC.smc_set_vector_s_profile(ConnectNo, CurrentCrd, 0, data.STime);
			LTSMC.smc_line_unit(ConnectNo, CurrentCrd, num, array, array2, (ushort)(data.IsAbsCoord ? 1 : 0));
		}
		/// <summary>
		/// 启动连续线性插补
		/// </summary>
		/// <param name="data"></param>
		public void SetContinueLineInter(ContinueLineInterData data)
        {
			//设置速度参数
			LTSMC.smc_conti_set_lookahead_mode(ConnectNo, CurrentCrd, data.Mode, 11, 10, data.AccSpeed);  //设置前瞻
			LTSMC.smc_set_vector_profile_unit(ConnectNo, CurrentCrd, 0.0, data.MaxSpeed, data.AccTime, data.DecTime, 0.0);
			LTSMC.smc_set_vector_s_profile(ConnectNo, CurrentCrd, 0, data.STime);
			LTSMC.smc_conti_set_blend(ConnectNo, CurrentCrd, 1);
			LTSMC.smc_set_arc_limit(ConnectNo, CurrentCrd, 1, 0, 0);
			LTSMC.smc_stop_multicoor(ConnectNo, CurrentCrd, 1);  // 先停止
			// 轴数量
			ushort axisNum = (ushort)data.AxisDatas.Count;
			List<ushort> axiss = new List<ushort>();
            foreach (var item in data.AxisDatas.Keys)
            {
				axiss.Add((ushort)item);
			}
			ushort[] axisList = axiss.ToArray();
			// 设置有多少轴参与 分别是那些轴
			LTSMC.smc_conti_open_list(ConnectNo, CurrentCrd, axisNum, axisList);
			// 遍历所有的节点
			for (int i = 0; i < data.AxisDatas.First().Value.Count; i++)
            {
				// 读取每个轴的 运动坐标
				double [] pos = new double[axisList.Length];
                for (int j = 0; j < axisList.Length; j++)
                {
					pos[j] = data.AxisDatas[(Axis)axisList[j]][i];
				}
				LTSMC.smc_conti_line_unit(ConnectNo, CurrentCrd, axisNum, axisList, pos, 1, (ushort)(i + 1));
			}
			// 开始连续插补
			LTSMC.smc_conti_start_list(ConnectNo, CurrentCrd);
			// 关闭连续插补缓冲区
			LTSMC.smc_conti_close_list(ConnectNo, CurrentCrd);
		}

		/// <summary>
		/// 基于规划
		/// </summary>
		/// <param name="data"></param>
		public void SetContinueLineInterForTask(ContinueLineInterData data, double time)
        {
			CheckLinked();
			var tasks = data.ToTasks(time);
            foreach (var item in tasks)
            {
				var task = item.Value;
				this[item.Key].SetSingleAxisAnySpeedTask(task);
			}
			StartAxisesSpeedTask(tasks.Keys);
		}
		/// <summary>
		/// 绘制圆, 自行实现的，并不是基于插补
		/// </summary>
		/// <param name="data"></param>
		public void SetDrawCircle(DrawCircleData data)
		{
			CheckLinked();
			LTSMC_Axis lTSMC_Axis = LtsmcAxiss[data.HorAxis];
			LTSMC_Axis lTSMC_Axis2 = LtsmcAxiss[data.VecAxis];
			data.GetDrawCircData();
			lTSMC_Axis.SetSingleAxisAnySpeedTask(data.Length, data.ToHorTimeArray, data.ToHorPositionArray, data.ToHorVelArray);
			lTSMC_Axis2.SetSingleAxisAnySpeedTask(data.Length, data.ToVecTimeArray, data.ToVecPositionArray, data.ToVecVelArray);

			StartAxisesSpeedTask(new Axis[] { data.HorAxis, data.VecAxis });
		}
		/// <summary>
		/// 启动多轴任务规划
		/// </summary>
		/// <param name="axes"></param>
		public void StartAxisesSpeedTask(IEnumerable<Axis> axes)
        {
			var axises = axes.Select(p => (ushort)p).ToArray();
			LTSMC.smc_pvt_move(ConnectNo, (ushort)axises.Length, axises);
		}
		/// <summary>
		/// 清空所有的告警 
		/// </summary>
		public void SetClearAllAxisWaring()
		{
			foreach (KeyValuePair<Axis, LTSMC_Axis> item in LtsmcAxiss)
			{
				item.Value.SetClearAxisWaring();
			}
		}
		/// <summary>
		/// 读取In pin口的状态
		/// </summary>
		/// <param name="port"></param>
		/// <returns></returns>
		public PortSatte ReadInPort(int port)
		{
			CheckLinked();
			if (port > 23 || port < 0)
			{
				return PortSatte.E;
			}
			var res = LTSMC.smc_read_inbit(ConnectNo, (ushort)port);
			switch(res)
			{
				case 0: return PortSatte.L;
				case 1: return PortSatte.H; 
				default: return PortSatte.E;
			};
		}
		/// <summary>
		/// 设置输出口的状态
		/// </summary>
		/// <param name="port"></param>
		/// <param name="state"></param>
		/// <returns></returns>
		public bool SetOutPort(int port, PortSatte state)
		{
			if (state == PortSatte.E)
			{
				return false;
			}
			short num = LTSMC.smc_write_outbit(ConnectNo, (ushort)port, (ushort)state);
			return true;
		}
	

		/// <summary>
		/// 所有轴归零运动
		/// </summary>
		public void AllToZero()
		{
			CheckLinked();
			foreach (KeyValuePair<Axis, LTSMC_Axis> item in LtsmcAxiss)
			{
				item.Value.SetStartFindZeroParameters();
			}
		}
		/// <summary>
		/// 所有轴的坐标清零
		/// </summary>
		public void AllToClearPositionZero()
		{
			foreach (KeyValuePair<Axis, LTSMC_Axis> item in LtsmcAxiss)
			{
				item.Value.PositionZeroClear();
			}
		}
		/// <summary>
		/// 减速停止并且运动
		/// </summary>
		/// <exception cref="LSTMCException"></exception>
		public void DecAndStopCrd()
		{
			if (!IsLink)
			{
				throw new LSTMCException("请先连接设备!");
			}
			LTSMC.smc_stop(ConnectNo, CurrentCrd, 0);
			ConnectNo = ushort.MaxValue;
		}
		/// <summary>
		/// 停止直线插补
		/// </summary>
		/// <exception cref="LSTMCException"></exception>
		public void StopLineInter()
		{
			if (!IsLink)
			{
				throw new LSTMCException("请先连接设备!");
			}
			LTSMC.smc_emg_stop(ConnectNo);
			ConnectNo = ushort.MaxValue;
		}
		/// <summary>
		/// 修改轴的连接状态
		/// </summary>
		/// <param name="state"></param>
		protected void ModifyAxissIsLink(bool state)
		{
			foreach (LTSMC_Axis value in LtsmcAxiss.Values)
			{
				value.IsLink = state;
			}
		}
		/// <summary>
		/// 关闭
		/// </summary>
		/// <param name="isStop"></param>
		public void Close(bool isStop = true)
		{
			if (isStop)
			{
				StopAll();
			}
			LTSMC.smc_board_close(ConnectNo);
			IsLink = false;
		}
		/// <summary>
		/// 停止所有的运动
		/// </summary>
		public void StopAll()
		{
			foreach (LTSMC_Axis value in LtsmcAxiss.Values)
			{
				value.Stop();
			}
		}
		/// <summary>
		/// 写入数据到设备空间
		/// </summary>
		/// <param name="datas"></param>
		/// <param name="start"></param>
		/// <returns></returns>
		/// <exception cref="LSTMCException"></exception>
		public bool WriteConfigToDevice(byte[] datas, ushort start = 0)
		{
			if (!IsLink)
			{
				throw new LSTMCException("请先连接设备!");
			}
			ushort inum = (ushort)datas.Length;
			if (LTSMC.smc_set_persistent_reg(ConnectNo, start, inum, datas) != 0)
			{
				return false;
			}
			return true;
		}
		/// <summary>
		/// 从设备空间读取数据
		/// </summary>
		/// <param name="datas"></param>
		/// <param name="start"></param>
		/// <returns></returns>
		/// <exception cref="LSTMCException"></exception>
		public bool ReadConfigByDevice(ref byte[] datas, ushort start = 0)
		{
			if (!IsLink)
			{
				throw new LSTMCException("请先连接设备!");
			}
			ushort inum = (ushort)datas.Length;
			if (LTSMC.smc_get_persistent_reg(ConnectNo, start, inum, datas) != 0)
			{
				return false;
			}
			return true;
		}
		/// <summary>
		/// 异常回调
		/// </summary>
		/// <param name="optionFunction"></param>
		/// <param name="erroCodes"></param>
		/// <exception cref="LSTMCException"></exception>
		protected void CallBack(string optionFunction, params short[] erroCodes)
		{
			ErroType erroType = ErroType.EMPTY;
			StringBuilder stringBuilder = new StringBuilder();
			foreach (short num in erroCodes)
			{
				if (num != 0)
				{
					ErroType enumTypeByType = num.GetEnumTypeByType<ErroType, short>();
					stringBuilder.Append("错误" + enumTypeByType.ToString() + " : " + Tools.GetErroTypeTip(enumTypeByType) + "\n");
					erroType |= enumTypeByType;
				}
			}
			if (stringBuilder.Length == 0)
			{
				return;
			}
			throw new LSTMCException(string.Format("错误信息:{0}, 错误编码:{1}, 错误函数:{2}, 错误轴向:{3}", stringBuilder.ToString(), ((Func<short[], string>)delegate(short[] codes)
			{
				string text = "";
				foreach (short num2 in codes)
				{
					text = text + num2 + " ";
				}
				return text;
			})(erroCodes), optionFunction, "总控制"));
		}
	}
}
